#include "Scene02.h"

Scene02::Scene02(Managers *managers)
{
	this ->managers = managers;

	currentCam = NULL;
}

Scene02::~Scene02(void)
{
	if (framebuffer != NULL)
		delete framebuffer;

	if (orTexture != NULL)
		delete orTexture;

	if (blur != NULL)
		delete blur;

	if (orDepthTexture != NULL)
		delete orDepthTexture;
}

void Scene02::Initialize()
{
	fadeMod = 0.0f;
	fade = 1.0f;

	ZeroMemory(idm, sizeof(float) * 16);
	idm[0] = 1.0f;
	idm[5] = 1.0f;
	idm[10] = 1.0f;
	idm[15] = 1.0f;

	vpSpecular = managers ->vertexShaderMan ->Get("specular");
	fpSpecular = managers ->pixelShaderMan ->Get("specular");
	vpDof = managers ->vertexShaderMan ->Get("dof");
	fpDof = managers ->pixelShaderMan ->Get("dof");
	vpBlur = managers ->vertexShaderMan ->Get("blur");
	fpBlur = managers ->pixelShaderMan ->Get("blur");

	cgpSpotLightPos = cgGetNamedParameter(fpSpecular ->GetProgram(), "spotLightPos");
	cgpSpotLightTargetPos = cgGetNamedParameter(fpSpecular ->GetProgram(), "spotLightTargetPos");
	modelMatrix = cgGetNamedParameter(vpSpecular ->GetProgram(), "modelMatrix");
	cgpFade = cgGetNamedParameter(fpDof ->GetProgram(), "fade");

	courtyard = managers ->modelMan ->Get("scene02");
	skybox = managers ->modelMan ->Get("skybox");

	anim = managers ->animMan ->Get("scene02");

	scena2camera1 = managers ->camerasManager ->Get("scena2camera1");
	scena2camera2 = managers ->camerasManager ->Get("scena2camera2");
	scena2camera3 = managers ->camerasManager ->Get("scena2camera3");
	scena2camera4 = managers ->camerasManager ->Get("scena2camera4");
	scena2camera5 = managers ->camerasManager ->Get("scena2camera5");
	
	framebuffer = new Framebuffer();
	framebuffer ->Initialize(1024, 1024, 32);

	orTexture = new Texture(1024, 1024, 32, NULL);
	orTexture ->BindTexture();
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
	glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);

	orDepthTexture = new DepthTexture(1024, 1024);

	blur = new Blur(framebuffer, 3, 1, vpBlur, fpBlur);

	currentCam = managers ->camerasManager ->Get("SteerCamera");

	cgGLSetParameter1f(cgpFade, 1.0f);

	SetAnimation();
}

void Scene02::Render(float ms)
{
	//currentCam = managers ->camerasManager ->Get("SteerCamera");

	fade += fadeMod * (ms / 1000.0f);
	fade = min(1.0f, max(fade, 0.0f));

	cgGLSetParameter1f(cgpFade, fade);

	if (currentCam == NULL)
		return;

	vpSpecular ->DoShader();
	fpSpecular ->DoShader();

	framebuffer ->AttachColorTexture(orTexture ->GetId());
	framebuffer ->AttachDepthTexture(orDepthTexture ->GetId());
	framebuffer ->StartRenderToTexture();
	glViewport(0, 0, 1024, 1024);

	anim ->Process(ms);
	anim ->ProcessAnimatables(ms);

	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glScalef(0.01f, 0.01f, 0.01f);

	currentCam ->Process(ms);
	currentCam ->SetViewMatrix();

	cgGLDisableProfile(CG_PROFILE_VP30);
	cgGLDisableProfile(CG_PROFILE_FP30);
	cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpDof ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);
	glEnable(GL_TEXTURE_2D);
	glDisable(GL_LIGHTING);
	glDepthMask(GL_FALSE);
	sm::Vec3 eyePos = currentCam ->GetPosition();
	glTranslatef(eyePos.x, eyePos.y, eyePos.z);
	//cgGLSetParameter1f(cgGetNamedParameter(fpSpecular ->GetProgram(), "focalDistance"), 99999.0f);
	skybox ->Render();
	glTranslatef(-eyePos.x, -eyePos.y, -eyePos.z);
	glDepthMask(GL_TRUE);

	/*cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpSpecular ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);*/

	vpSpecular ->DoShader();
	fpSpecular ->DoShader();

	cgGLSetParameter3f(cgGetNamedParameter(fpSpecular ->GetProgram(), "lightPosition"), 100, 1000, 100);	
	cgGLSetParameter3f(cgGetNamedParameter(fpSpecular ->GetProgram(), "eyePosition"), eyePos.x, eyePos.y, eyePos.z);
	cgGLSetParameter1f(cgGetNamedParameter(fpSpecular ->GetProgram(), "focalDistance"), currentCam ->GetTargetDistance());

	cgGLSetMatrixParameterfc(modelMatrix, idm);

	courtyard ->Render();

	framebuffer ->FinishRenderToTexture();

	blur ->MakeBlur(orTexture ->GetId());

	glDisable(GL_DEPTH_TEST);

	glMatrixMode(GL_PROJECTION);
	glPushMatrix();
	glLoadIdentity();
	gluOrtho2D(0, 1280, 0, 1024);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	glViewport(0, 0, 1280, 1024);

	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();

	vpDof ->DoShader();
	fpDof ->DoShader();

	cgGLSetStateMatrixParameter(
		cgGetNamedParameter(vpDof ->GetProgram(), "modelViewProj"),
		CG_GL_MODELVIEW_PROJECTION_MATRIX, CG_GL_MATRIX_IDENTITY);

	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex0"), orTexture ->GetId());
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex0"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex1"), blur ->GetBlurredTexture(0));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex1"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex2"), blur ->GetBlurredTexture(1));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex2"));
	cgGLSetTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex3"), blur ->GetBlurredTexture(2));
	cgGLEnableTextureParameter(cgGetNamedParameter(fpDof ->GetProgram(), "tex3"));

	glBegin(GL_QUADS);
	glTexCoord2f(0, 0); glVertex2f(0, 0);
	glTexCoord2f(1, 0); glVertex2f(1280, 0);
	glTexCoord2f(1, 1); glVertex2f(1280, 1024);
	glTexCoord2f(0, 1); glVertex2f(0, 1024);
	glEnd();

	cgGLDisableProfile(CG_PROFILE_VP30);
	cgGLDisableProfile(CG_PROFILE_FP30);

	glMatrixMode(GL_PROJECTION);
	glPopMatrix();
	glMatrixMode(GL_MODELVIEW);

	glEnable(GL_DEPTH_TEST);
}

void Scene02::Notify(float time, const char *type, const char *value)
{
	if (strcmp(type, "camera") == 0)
	{
		currentCam = managers ->camerasManager ->Get(value);
	}

	if (strcmp(type, "effect") == 0)
	{
		if (strcmp(value, "fadedown") == 0)
		{
			fadeMod = -1.0f;
		}

		if (strcmp(value, "fadeup") == 0)
		{
			fadeMod = 1.0f;
		}
	}
}

void Scene02::SetLights()
{
	ZeroMemory(lights, sizeof(float) * 3 * 17);

	Light *light;
	sm::Vec3 lightPos;
	sm::Vec3 lightTargetPos;
	char name[1024];

	int lightIndex = 0;

	for (int i = 0; i < managers ->lightsManager ->GetCount(); i++)
	{
		managers ->lightsManager ->Get(i, name, light);

		if (strstr(name, "scena2") != NULL)
		{
			lightPos = light ->GetPosition();
			lightTargetPos = light ->GetTargetPosition();
			lights[(lightIndex * 3) + 0] = lightPos.x;
			lights[(lightIndex * 3) + 1] = lightPos.y;
			lights[(lightIndex * 3) + 2] = lightPos.z;
			lightsTargets[(lightIndex * 3) + 0] = lightTargetPos.x;
			lightsTargets[(lightIndex * 3) + 1] = lightTargetPos.y;
			lightsTargets[(lightIndex * 3) + 2] = lightTargetPos.z;

			lightIndex++;

			anim ->AttachAnimatable(light);
			anim ->AttachAnimatable(light ->GetTarget());
		}
	}

	cgGLSetParameterArray3f(cgpSpotLightPos, 0, 17, lights);	
	cgGLSetParameterArray3f(cgpSpotLightTargetPos, 0, 17, lightsTargets);
}

void Scene02::SetAnimation()
{
	anim ->AttachAnimatable(scena2camera1);
	anim ->AttachAnimatable(scena2camera1 ->GetTarget());
	anim ->AttachAnimatable(scena2camera2);
	anim ->AttachAnimatable(scena2camera2 ->GetTarget());
	anim ->AttachAnimatable(scena2camera3);
	anim ->AttachAnimatable(scena2camera3 ->GetTarget());
	anim ->AttachAnimatable(scena2camera4);
	anim ->AttachAnimatable(scena2camera4 ->GetTarget());
	anim ->AttachAnimatable(scena2camera5);
	anim ->AttachAnimatable(scena2camera5 ->GetTarget());
}

void Scene02::Prepare()
{
	SetLights();
}
